/* call 模拟实现 */
Function.prototype.call2 = function(context) {
    context = Object(context) || window;
    context.fn = this;
    let arr = []
    for (let i = 1, len = arguments.length; i < len; i++) {
        arr.push('arguments[' + i + ']');
    }
    const result = eval('context.fn(' + arr + ')');

    delete context.fn;

    return result;
};

/**
 * [apply2 apply 模拟实现]
 * @param  {[type]} context [description]
 * @param  {[type]} arr     [description]
 * @return {[type]}         [description]
 * @author zhangguanggui 2018-08-01
 */
Function.prototype.apply2 = function(context, arr) {
    context = Object(context) || window;
    context.fn = this;
    let result;
    if (!arr) {
        result = context.fn();
    } else {
        if (!Array.isArray(arr)) {
            throw new Error('argument arr must be Array');
        }
        result = eval('context(' + arr + ')');
    }


    delete context.fn;
    return result;
};



/**
 * [bind2 bind模拟实现]
 * @param  {[type]} context [description]
 * @return {[type]}         [description]
 * @author zhangguanggui 2018-08-01
 */
Function.prototype.bind2 = function(context) {
    if (typeof this !== 'function') {
        throw new Error('bind can only use for function');
    }
    const that = this;
    const _args = [].slice.call(arguments, 1);

    // 构造函数设置原型
    function Fproto() {}
    Fproto.prototype = this.prototype;

    function fbind() {
        const args = _args.concat([].slice.call(arguments))
        that.apply(this instanceof Fproto ? this : context, args);
    }

    fbind.prototype = new Fproto();

    return fbind;
};




let o = {
    name: 'zgg',
    age: 22,
    say(nn) {
        console.log(this.name + '--' + this.age + '--' + nn)
    }
}


o.say.call2({ name: 'bob', age: 100 }, 'rrr');
o.say.call2({ name: 'bob', age: 100 });